Boilerplate 1. Semester¶
Linked List¶
public class Shop {
public static void main(String[] args) {
ShoppingList list = new ShoppingList();
ShoppingListItem brot = new ShoppingListItem("Brot", 4.5, TaxClass.REDUCED);
ShoppingListItem duschgel = new ShoppingListItem("Duschgel", 1.99, TaxClass.FULL);
ShoppingListItem marmelade = new ShoppingListItem("Marmelade", 1.32, TaxClass.REDUCED);
ShoppingListItem kaese = new ShoppingListItem("Käse", 0.99, TaxClass.REDUCED);
list.put(brot);
list.put(duschgel);
list.put(marmelade);
list.put(kaese);
System.out.println("Folgendes ist in der Liste: \n");
System.out.println(list.toString());
System.out.println("\nTeste ob Elemente in der Liste sind ...");
System.out.println("Duschgel in der Liste: " + list.isInList(duschgel));
System.out.println("\nHole Elemente aus der Liste: ");
System.out.println(list.get("Brot"));
System.out.println(list.get("Nicht in der Liste") + " (sollte sein: null)");
System.out.println("Entferne 'Käse'...");
list.remove("Käse");
System.out.println(list.toString());
}
}
public class ShoppingList {
private ShoppingListLinkItem head;
public void put(ShoppingListItem item) {
head = new ShoppingListLinkItem(item, head);
}
public ShoppingListItem get(String name) {
ShoppingListLinkItem tempHead = head;
while (!tempHead.data.getName().equals(name)) {
tempHead = tempHead.next;
if (tempHead == null)
return null;
}
return tempHead.data;
}
public void remove(String name) {
// Item at the start
if (head == null ) {
return;
} else if (head.data.getName().equals(name)) {
head = head.next;
}
// Item at the mid or end
ShoppingListLinkItem tempHead = head;
while (true) {
if (tempHead.next == null) {
return; // end from the list (next item null) -> item not found
} else if (tempHead.next.data.getName().equals(name)) {
tempHead.next = tempHead.next.next; // Overwrite pointer from the removable item
return;
}
tempHead = tempHead.next;
}
}
public boolean isInList(ShoppingListItem item) {
ShoppingListLinkItem tempHead = head;
while (!tempHead.data.equals(item)) {
tempHead = tempHead.next;
if (tempHead == null)
return false;
}
return true;
}
public String toString() {
StringBuilder str = new StringBuilder("{");
ShoppingListLinkItem tempHead = head;
while (tempHead != null) {
str.append(tempHead.data.toString() + ", ");
tempHead = tempHead.next;
}
return str.substring(0, str.length()-2) + "}";
}
}
public class ShoppingListLinkItem {
ShoppingListItem data;
ShoppingListLinkItem next;
public ShoppingListLinkItem(ShoppingListItem data, ShoppingListLinkItem next) {
this.data = data;
this.next = next;
}
}
Rekursiv¶
public static int binarySearchRec(int[] arr, int value) {
return binarySearchRec(arr, value, 0, arr.length - 1);
}
private static int binarySearchRec(int[] arr, int value, int left, int right) {
if (left > right) {
return -1;
}
int middle = (left + right) / 2;
if (arr[middle] < value) {
return binarySearchRec(arr, value, middle + 1, right);
} else if (arr[middle] > value) {
return binarySearchRec(arr, value, left, middle - 1);
} else {
return middle;
}
}
public static int countUnevenRec(int[] a) {
return countUnevenRec(a, 0);
}
private static int countUnevenRec(int[] a, int i) {
if (i >= a.length)
return 0;
return a[i] % 2 + countUnevenRec(a, i+1);
}
public static int ggT(int x, int y) {
if (x == y) {
return x;
} else if (x > y) {
return ggT(x - y, x);
}
return ggT(x, y - x);
}
public static long powRecursive(long x, long n) {
if (n == 0) {
return 1;
} else if ((n/2)*2 == n) {
long a = powRecursive(x, n/2);
return a * a;
}
return x * powRecursive(x, n-1);
}
public static long isFactorialRec(long i) {
if (i == 1) {
return 1;
}
return isFactorialRec(i, 2);
}
public static long isFactorialRec(long i, long div) {
long quota = i/div;
// termination conditions
if (quota * div != i) { // when it isn't a factorial
return -1;
} else if (quota == 1) { // when it is a factorial
return div;
}
// next call
return isFactorialRec(quota, div+1);
}
public static long factorialRecursive(long n) {
if (n == 0) return 1;
return (n > MAX_N) ? Long.MIN_VALUE : n * factorialRecursive(n-1);
}
public static void main(String[] args) {
for (int i = 0; i < 235; i++) {
System.out.println(i + ": " +factorialFor(i));
}
}
Enums¶
public enum TrafficLightColor {
RED(10) {
public int getBrightness(){
return 10;
}
},
RED_YELLOW(8), GREEN(5), YELLOW(10);
private int brightness;
private TrafficLightColor(int brightness) {
this.brightness = brightness;
}
public int getBrightness() {
return brightness;
}
public void setBrightness(int brightness) {
this.brightness = brightness;
}
}
public class TrafficLight {
private TrafficLightColor currentColor;
public void reset() {
currentColor = TrafficLightColor.RED;
}
public TrafficLightColor getCurrentColor() {
return currentColor;
}
public TrafficLightColor[] getAllColors() {
return TrafficLightColor.values();
}
public void setCurrentColor(TrafficLightColor color) {
this.currentColor = color;
}
public void doSwitch() {
switch (currentColor) {
case RED:
currentColor = TrafficLightColor.RED_YELLOW;
break;
case RED_YELLOW:
currentColor = TrafficLightColor.GREEN;
break;
case GREEN:
currentColor = TrafficLightColor.YELLOW;
break;
case YELLOW:
currentColor = TrafficLightColor.RED;
break;
}
}
public static void main (String[] args) {
System.out
.println("\nget one special value from string representation:");
TrafficLightColor single = TrafficLightColor.valueOf("RED");
System.out.println(single);
// Which position in the enum
System.out.println("Ordinal of GREEN:" + TrafficLightColor.GREEN.ordinal());
System.out.println("\nbrightness of RED: "
+ TrafficLightColor.RED.getBrightness());
TrafficLightColor.RED.setBrightness(6);
System.out.println("\nbrightness of RED: "
+ TrafficLightColor.RED.getBrightness()); //Still 10
}
}
Seiteneffekte¶
/**
* Half from a set to b and c
* a = 4 b = 3 c = 10 d = true f1 = 2.0
* @return b ()
*/
public int expressionA() {
return b = c = (a / 2);
}
/**
* Set a to 10 and multiply the value of a with 4
* @return b
*/
public int expressionB() {
return b = c = (a = 10) << 2;
}
/**
* Controls if a and c is divideable by 2
* @return boolean
*/
public boolean expressionC() {
return (a % 2 == 0) && (c % 2 == 0);
}
/**
*
* @return boolean
*/
public boolean expressionD() {
//return d & (f1) > 10 & (a = (int) f1) == a;
return d & (a = (int) f1) > 10;
}
public boolean expressionE() {
//return (b & 0b100) >> 2 == 1 && (b & 0b10) >> 1 == 1;
return (b&3<<1)==3<<1;
}
public void expressionF() {
f1 = ((a % 10 == 0) && (b % 10 == 0)) ? a / 3.0f : 10 * a;
}
Interfaces¶
package container2;
/**
* Specification of a simple stack
*/
public interface Stack {
void push(Object obj);
Object pop();
Object top();
boolean empty();
}
package container2;
/**
* A simple stack implementation backed by an array of fixed size, which can
* hold objects. Among other things an adequate error handling is missing
*/
public class StackArrayImpl implements Stack {
[ ... ]
public StackArrayImpl(int cap) { ... }
public void push(Object obj) { ... }
public Object pop() { ... }
public Object top() { ... }
public boolean empty() { ... }
public String toString() { ... }
}
package container2;
/** A simple stack implementation backed by a linked list of
* objects.
* Among other things an adequate error handling is missing
*/
public class StackLinkedListImpl implements Stack {
[...]
public void push(Object c) { ... }
public Object pop() { ... }
public Object top() { ... }
public boolean empty() { ... }
public String toString() { ... }
}
class ListLinkElement { ... }
Verhaltenspakete¶
Interface "erzwingen" einen gemeinsammen Verhaltensaskept (gleiche Methoden) verschiedener Klassen -> notwendig um Callback zu realisieren
Interface:
public interface Callback {
void callback();
}
Implementierung des Interface:
public class CallbackImpl implements Callback{
@Override
public void callback() {
System.out.println("I am the callback");
}
}
Ausführung des Interfaces:
public class Main {
public static void main(String[] args) {
CallbackImpl myCallback = new CallbackImpl();
methodThatExpectsACallback(myCallback);
// Alternativ mit Lambda, da nur eine Methode im Interface
methodThatExpectsACallback(() -> System.out.println("I am the callback from the Lambda"));
}
private static void methodThatExpectsACallback(Callback callback){
System.out.println("I am the method.");
callback.callback();
}
}
API-Interfaces von java.lang¶
Cloneable¶
Interface hat keine Methode -> dient zur Markierung, dass ein Objekt geklont werden darf.
Die protected clone() Methode kann zu einer plublic Methode überschrieben werden.
public MyClass clone() throws CloneNotSupportedException {
MyClass newClass = (MyClass) super.clone();
// TODO: clone of reference variables
// clone of immutable object not necessary
return s;
}
Complarable¶
Klassen erhalten dadurch eine Ordnung, die durch einen Integer repräsentiert wird
Zu implementierende Methode:
public int compareTo(Object o) // with significant return values <0, 0, >0;
Exceptions¶
try {
// Code here can throw exception
} catch (SomeException e) {
// handle SomeException
} catch (FooException | BaaException e) {
// handle FooException or BaaException
} finally {
// cleen up
// code here will be always executed
}
Werfen von Exceptions¶
throw new SomeException("Exception here");
Eigene Exceptions¶
public class MyException extends Exception {
public MyException () { super(); }
public MyException (String s) { super(s); }
}
java.lang.Error: Verwendung für Fehler in der Laufzeitumgebungjava.lang.Exception: checked exception -> müssen gecatched werden- Verwendung für voraussichtliche Probleme, die während der normalen Programmausführung auftreten können
java.lang.RuntimeException: unchecked exception -> können gecatched werden- Verwendung für fehlerhafte Programmierung oder ...
- Benutzerdefinierte Exceptions
Geschachtetlte Klassen¶
Innere Klasse¶
wenn Klasse in mehreren Methoden verwendet wird
modifier class A {
// Attributes Class A
// [...]
modifier class B {
// Attributes Class B
// [...]
}
}
Statische innere Klasse¶
wenn kein Zugriff auf Objektattribute nötig
modifier class A {
// Attributes Class A
// [...]
static modifier class B {
// Attributes Class B
// [...]
}
}
Anonyme Klasse¶
Wenn nur einmal im Code verwendet
modifier class A {
// Attributes Class A
// [...]
BaseClass anonymous = new BaseClass() {
// variables and methods of anonymous class
// ...
}
}
Lokale Klasse¶
Wenn mehrfach in einer Methode
modifier class A {
// Attributes Class A
// [...]
modifier method(...) {
static modifier class B {
// Attributes Class B
// [...]
}
}
}
Die Klassen java.util.Enumeration und java.util.Interator¶
Enumeration:
Generates a series of elements, one at a time. Successive calls to the nextElement() method return successive elements of the series.
public interface Enumeration<E> {
boolean hasMoreElements();
E nextElement(); // returns next element and points to it
default Iterator<E> asIterator() {
return new Iterator<>() {
@Override public boolean hasNext() {
return hasMoreElements();
}
@Override public E next() {
return nextElement();
}
};
}
}
Iterator:
Takes the place of Enumeration in the Java Collections Framework.
Differ from enumerations in two ways:
- Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
- Method names have been improved.
public interface Iterator<E> {
boolean hasNext();
E next();
/**
* Removes from the underlying collection the last element returned
* by this iterator (optional operation).
*
* This method can be called only once per call to next.
*
* @throws UnsupportedOperationException if the `remove`
* operation is not supported (implemented) by this iterator
*
* @throws IllegalStateException if the `next` method has not
* yet been called, or the `remove` method has already
* been called after the last call to the `next` method
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
// [...]
}
Example:
To print all elements of a Vector<E> v:
for (Enumeration<E> e = v.elements(); e.hasMoreElements();)
System.out.println(e.nextElement());
Unittests¶
JUnit gehör nicht zum JDK und muss seperat im CLASSPATH zur Verfügung stehen
class ClassTest {
// classvariables here will be persistent
@BeforeAll
static void setupBeforeAll() throws Exception{
}
@AfterAll
static void tearDownBeforeAll() throws Exception{
}
@BeforeEach
void setup() throws Exception {
}
@AfterEach
void tearDown() throws Exception {
}
@Test
public void testSomething() {
// here one of your tests
}
}
Assert-Statements¶
@Test
void demonstrateAssert() {
int i = 5;
int j = 6;
assertEquals(i, j, "a message");
}
Test-Suiten - Zusammenfassen mehrerer Unit-Tests¶
@Suite
@SelectClasses({
SomeTestClassA.class,
SomeTestClassB.class
})
public class ATestSuite {
}
Mocking¶
creating objects that simulate the behaviour of real objects
Mock-Objekt dient als Dummy-Objekt anstelle eines realen Objekts, welches bislang nicht zum Testen zur Verfügung steht oder schlecht dafür geeignet ist.
Metaprogramming¶
Geschriebene Programme, die andere Programme repräsentieren oder manipulieren
Verwendung in der Praxis:
- Generative Programmierung (Bsp.: Codegenerierung mit Schablonen)
- Reflection (Programm untersucht sich selber)
- ...
Introspection und Reflection¶
Introspection: Klassen können (im Plugin) zur Laufzeit angeschaut werden
- Informationen über elementare Datentypen, Arrays und Klassen zur Laufzeit
- JVM Informationen von Class-Files als Meta-Objekt zur Verfügung Reflection: Neue Klassen können zur Laufzeit geladen und instanziiert werden
- Meta-Objekte von der JVM können verändert werden
Einsatzgebiete:
- Plugins
- Frameworks
- Serialisierung
- ...
Die zentrale Klasse java.lang.Class¶
kann durch Aufruf von
getClass()einer Klasse erhalten werden
oder duch Konstante<package.to.Classname>.class(wenn die Klasse zur Kompilezeit vorliegt)
Wichtigste Methoden:
getName() : String-> returns the name of the classisInterface() : booleanisArray() : booleanisPrimitive() : boolean-> Primitiver DatentypgetModifiers() : int-> Kann mitModifier.toString()decodiert werdengetSuperClass() : ClassgetInterfaces : Class[]getMethods : Method[]getDeclaredMethod(String name, Class[] parameterTypes) : Method- Weitere: https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/lang/Class.html#method-summary
Weitere Metaklassen in java.lang.reflect
Method: stellt eine Methode innerhalb einer Klasse darField: z.B. für Variablen -> auslesen und setzen von WertenConstructor: erlabut Erzeugen von neuen Instanzen der beobachteten KlasseModifier: condiert als int-Wert (bietet methode zom decodieren)Array: enthält statische Methoden zum dynamischen Kreieren und Manipulieren von Arrays
Dynamisches Laden von Klassen¶
Class<?> clazz = Class.forName("MyClass");
Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[] {/*Parameters type(s)*/});
MyClass myClass = (MyClass) constructor.newInstance(new Object[] {/*Parameters value(s)*/});
myClass.myPublicMethod(); // e.g. call a public method
// private methoden aufrufen
Method privMethod = clazz.getDeclaredMethod("myPrivateMethod", new Class[] {});
privMethod.setAccessible(true);
privMethod.invoke(myClass); // invoke this private method from myClass object
Annotationen¶
Geben zusätzliche Informationen, welche nicht der eigentlichen Logik des Progammes sind
Vordefinierte Annotationen¶
Dient zur Steuerung des Compilers, um den Entwickler auf bestimmte Tatsachen hinzuweisen
Beispiele dafür sind:
@Deprecated@Override@SuppressWarnings
Selbstdefinierte Annotationen¶
Erlaubt es den Code mit Eigenschaften zu beschreiben
-> Wichtig zum Beispiel im Kotext der Reflection, bzw. Frameworks
Benutzung und Definierung einer eigenen Annotation:
// simple annotation
public @interface MyMarker {}
// usage:
@MyMarker
public void myMethod1() { ... }
// with named attributes
public @interface ToDo {
String what();
int count() default 1;
}
// usage:
@ToDo (what="execute", count=3)
public myMethod2() { ... }
public @interface Name {
String first();
String last();
}
// complex annotation
public @interface Reviewer {
Name value();
}
// usage:
@Reviewer(@Name(first="Joe", last="Doe"))
public void myMethod3() { ... }
Beispiel mit Reflection:
...
Method[] methods = clazz.getMethods();
for (method : methods) {
ToDo toDo = method.getAnnotation(ToDo.class);
if (toDo != null) {
for (int i = 0; i < toDo.count(); i++)
method.invoke(myClass);
}
}
Junit-Framework aggiert nach dem selben Prinzip
Generics¶
public class SingleObjectHolder<E> {
private E element;
public void put(E element) {
this.element = element;
}
public E get() {
return element;
}
}
Verwendung:
SingleObjectHolder<String> strHolder = new SingleObjectHolder<>();
strHolder.put("Hello");
String s = strHolder.get();
SingleObjectHolder<char[]> charArrHolder = new SingleObjectHolder<>();
charArrHolder.put(new char[]{'a', 'b', 'c'});
char c = charArrHolder.get()[0];
Generics bei Methoden¶
// hier Generic nicht unbeding notwendig, da folgendes auch mit
// upcast zu Object möglich ist
public static <T> void swap(T[] a, int i, int j) {
T t = a[i];
a[i] = a[j];
a[j] = t;
}
public static <T> T getLast(T[] a) {
return a[a.lenght-1];
}
Verwendung:
int[] ia = {1, 2, 3, 4};
// Implicit
swap(ia, 0, 1);
String s = getLast(ia);
// Explicit
ClassName.<Integer>swap(ia, 0, 1);
s = ClassName.<String>getLast(ia);
Grenzen¶
- Generics können keine primitive Datentypen sein
- keine statischen Variablen mit Generic-Typ
- Generic kann nicht mit
instanceofverwendet werden - Generic kann nicht im Zusammenhang mit
newverwendet werden
Beispiele:
// Geht nicht!!!
public static <T> T makeInstance() {
return new T();
}
// Ausweg
public static <T> T makeInstance(Class<T> clazz) {
return clazz.newInstance();
}
// Aufruf
makeInstance(MyClass.class);
// Geht nicht!!!
public static <T> T[] resize(T[] a) {
T[] cl new T[a.length + 1];
return cl;
}
// Ausweg
public static <T> T[] resize(T[] a, Class<T> elementType) {
T[] cl = (T[]) Array.newInstance(elementType, a.length + 1);
return cl;
}
// Aufruf
makeInstance(myClassArr, MyClass.class);
Mit Vererbung¶
// Parent class
class A<T> { }
class B<T> extends A { } // allowed not recomendet
class B<T> extends A<T> { } // better, B and A have same generic
class B extends A<T> { } // not allowed
class B extends A<String> { } // allowed
class B<T> extends A<String> { } // also allowed
Vorsicht:
Kein Typcast möglich
A<String> a1 = new A<>();
A<Integer> a2 = new A<>();
a1 = (A<String>) a2; // not allowed
Wildcards¶
Unbounded¶
A<Integer> intA = new A<>();
A rawA = intA; // warning: should be parameterized
intA = rawA; // warning: type safety
A<?> unboundedA = intA; // no warning
intA = unboundedA; // error: type mismatch
Upperbounded¶
class A<T extends Number>
-> Typparameter kann nur Number oder unterhalb von Number (Double, Interger, etc.) sein
Mit Interfaces:
class A<T extends MyClass & MyInterface1 & MyInterface2 & MyInterface3>
Lowerbounded¶
Schränken Parameter-Typ ein
static void doIt(B<? super Integer> b)-> Erlaubt Supertypes und sich selbst (
Integer,Number,Object)
Mit Reflection¶
Die Klasse Class selbst ist parametrisierbar (Class<T>)
Class<String> strClass;
Class<?> unboundClass;
/// returns the exact paramised type
strClass = String.class;
unboundClass = String.class; // Also allowed
/// returns only with wildcard paramised type
strClass = (Class<String>) "abc".getClass(); // warning: Type safety
unboundClass = "abc".getClass();
// Needs to be checked with ClassNotFoundException
strClass = (Class<String>) Class.forName("java.lang.String"); // warning: Type safety
unboundClass = Class.forName("java.lang.String");
Java Collections Framework¶
Collections Interface¶
| Method | Description |
|---|---|
| add(Object) | This method is used to add an object to the collection. |
| addAll(Collection c) | This method adds all the elements in the given collection to this collection. |
| clear() | This method removes all of the elements from this collection. |
| contains(Object o) | This method returns true if the collection contains the specified element. |
| containsAll(Collection c) | This method returns true if the collection contains all of the elements in the given collection. |
| equals(Object o) | This method compares the specified object with this collection for equality. |
| hashCode() | This method is used to return the hash code value for this collection. |
| isEmpty() | This method returns true if this collection contains no elements. |
| iterator() | This method returns an iterator over the elements in this collection. |
| parallelStream() | This method returns a parallel Stream with this collection as its source. |
| remove(Object o) | This method is used to remove the given object from the collection. If there are duplicate values, then this method removes the first occurrence of the object. |
| removeAll(Collection c) | This method is used to remove all the objects mentioned in the given collection from the collection. |
| removeIf(Predicate filter) | This method is used to remove all the elements of this collection that satisfy the given predicate. |
| retainAll(Collection c) | This method is used to retain only the elements in this collection that are contained in the specified collection. |
| size() | This method is used to return the number of elements in the collection. |
| spliterator() | This method is used to create a Spliterator over the elements in this collection. |
| stream() | This method is used to return a sequential Stream with this collection as its source. |
| toArray() | This method is used to return an array containing all of the elements in this collection. |
| Interfaces | that Extend the Java Collections Interface |
-> das Collection interface implementiert Iterator interface
Map Interface¶
repräsentiert durch Schlüssel-Wert-Paare
Iterieren über den Inhalt einer Map:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
...
}
Allgemeine Collection-Implementierungen im JDK¶
Implementierung von:
- List
ArrayListVector(thread-safe)LinkedList
- Queue und Deque
LinkedListArrayDequePriorityQueue
- Set
HashSetLinkedHashSetEnumSet
- SortedSet
TreeSet
- Map
Hashtable(thread-safe)HashMapWeakHashMapIdentityHashMap
- SortedMap
TreeSet
Lambdas¶
Interne Iteration¶
Rahmen:
class IntArrayUtils {
public static void forEach(int[] array, IntConsumer consumer) {
for (int value : array) {
consumer.accept(value);
}
}
}
Dazugehöriges Interface:
interface IntConsumer {
void accept(int value);
}
Benutzung:
-> Mit anonymen Klassen:
int[] array = {1, 2, 3};
IntArrayUtils.forEach(array, new IntConsumer(){
@Override
public void accept(int value) {
System.out.println(value);
}
});
IntArrayUtils.forEach(array, new IntConsumer(){
@Override
public void accept(int value) {
if (value%2 == 0)
System.out.println(value);
}
});
-> Mit Lambdas:
int[] array = {1, 2, 3};
IntArrayUtils.forEach(array, i -> System.out.println(i));
IntConsumer printIfOdd = i -> {
if (value%2 == 0)
System.out.println(value);
}
IntArrayUtils.forEach(array, printIfOdd);